package com.black.app.service.impl.exercise;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.black.app.domain.exercise.AppExercisePart;
import com.black.app.domain.exercise.AppExerciseSeries;
import com.black.app.domain.exercise.AppExerciseType;
import com.black.app.domain.req.exercise.type.ExerciseTypeAddReq;
import com.black.app.domain.req.exercise.type.ExerciseTypeEditReq;
import com.black.app.domain.resp.exercise.*;
import com.black.app.service.exercise.AppExercisePartService;
import com.black.app.service.exercise.AppExerciseSeriesService;
import com.black.app.service.exercise.AppExerciseTypeService;
import com.black.app.mapper.exercise.AppExerciseTypeMapper;
import com.black.common.exception.ServiceException;
import com.black.common.exception.database.RecordNotFoundException;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author L
 * @description 针对表【app_exercise_type(锻炼大分类)】的数据库操作Service实现
 * @createDate 2024-10-23 16:57:08
 */
@Service
public class AppExerciseTypeServiceImpl extends ServiceImpl<AppExerciseTypeMapper, AppExerciseType>
        implements AppExerciseTypeService {

    /**
     * 练习相关的业务
     */
    @Lazy
    @Autowired
    private AppExerciseSeriesService exerciseSeriesService;

    /**
     * 锻炼部位的业务
     */
    @Autowired
    private AppExercisePartService exercisePartService;

    /**
     * 获取所有类型树
     *
     * @return
     */
    @Override
    public List<AppTypeTreeResp> allTypeTree() {
        List<AppExerciseType> appExerciseTypes = this.baseMapper.getAllType();
        List<AppTypeTreeResp> appTypeTreeResp = this.buildTypeTree(appExerciseTypes);
        return appTypeTreeResp;
    }

    /**
     * 获取首页锻炼类型树
     *
     * @return
     */
    @Override
    public List<AppExerciseTreeResp> homeExerciseTree() {
        List<AppExerciseTreeResp> AppExerciseTreeRespList = new ArrayList<>();

        //查询所有类型
        List<AppExerciseType> appExerciseTypes = this.baseMapper.getAllType();
        //遍历所有为0的数据
        appExerciseTypes.stream().filter(item -> item.getParentId() == 0).forEach(item -> {
            //第一级没有图片
            AppExerciseTreeResp parent = new AppExerciseTreeResp();
            parent.setId(item.getTypeId());
            parent.setComponentType(item.getComponentType());
            parent.setName(item.getTypeName());
            parent.setOrderNum(item.getOrderNum());

            //有下一级
            if (item.getComponentType() == 3) {
                parent.setComponentType(3);
                buildChildrenPart(parent);
            } else {
                //没有下一级  查询 一张图，还是2张图的 app_exercise_series
                if (item.getComponentType() == 1) {
                    buildChildrenOneService(parent);
                } else {
                    buildChildrenTwoService(parent);
                }

            }

            AppExerciseTreeRespList.add(parent);
        });

        return AppExerciseTreeRespList;
    }


    /**
     * 2张图
     *
     * @param parent
     */
    private void buildChildrenTwoService(AppExerciseTreeResp parent) {
        //分页查询，只显示前2张
        PageInfo<AppExerciseSeries> pageInfo = this.exerciseSeriesService.findByTidTop2(parent.getId());
        //构造子节点对象
        List<AppExerciseSuper> childrenList = new ArrayList<>();

        //循环数据库的值，转换成自已需要的对象
        pageInfo.getList().forEach(item -> {
            AppExerciseSeriesResp appExerciseSeriesResp = new AppExerciseSeriesResp();
            appExerciseSeriesResp.setId(item.getSeriesId());
            appExerciseSeriesResp.setName(item.getTitle());
            appExerciseSeriesResp.setPath(item.getPath());
            appExerciseSeriesResp.setTime(item.getTime());
            appExerciseSeriesResp.setConsume(item.getConsume());
            appExerciseSeriesResp.setComponentType(parent.getComponentType());
            appExerciseSeriesResp.setTid(item.getTId());
            appExerciseSeriesResp.setEquip(item.getEquip());
            appExerciseSeriesResp.setFocus(item.getFocus());

            childrenList.add(appExerciseSeriesResp);
        });

        //给上一级设定子节点
        parent.setChildren(childrenList);
        //因为我们只显示了2个系列，所以判断一下，如果还有更多，就设置true
        parent.setHasMore(pageInfo.isHasNextPage());
    }

    /**
     * 查询锻炼部位的数据
     *
     * @param parent
     */
    private void buildChildrenPart(AppExerciseTreeResp parent) {
        List<AppExercisePartResp> list = this.exercisePartService.findByTidAll(parent.getId());
        //设定子类的组件类型
        list.forEach(item -> {
            item.setComponentType(parent.getComponentType());
        });
        parent.setChildren(list);
    }

    /**
     * 1张图的系列
     *
     * @param parent
     */
    private void buildChildrenOneService(AppExerciseTreeResp parent) {
        List<AppExerciseSeries> list = this.exerciseSeriesService.findByTidAll(parent.getId());
        List<AppExerciseSeriesResp> childrenList = new ArrayList<>();
        list.forEach(item -> {
            AppExerciseSeriesResp appExerciseSeriesResp = new AppExerciseSeriesResp();
            setAppExerciseSeriesResp(item, appExerciseSeriesResp);
            appExerciseSeriesResp.setComponentType(parent.getComponentType());
            childrenList.add(appExerciseSeriesResp);
        });
        parent.setChildren(childrenList);
    }

    /**
     * 构建类型树
     *
     * @param appExerciseTypes
     * @return
     */
    private List<AppTypeTreeResp> buildTypeTree(List<AppExerciseType> appExerciseTypes) {
        List<AppTypeTreeResp> appTypeTreeRespList = new ArrayList<>();

        // 查询根节点
        appExerciseTypes.stream().filter(p -> p.getParentId().intValue() == 0).forEach(item -> {
            AppTypeTreeResp root = new AppTypeTreeResp();
            root.setTypeId(item.getTypeId());
            root.setLabel(item.getTypeName());
            // 递归构建子节点
            buildChildrenTypeTree(root, appExerciseTypes);

            appTypeTreeRespList.add(root);
        });
        return appTypeTreeRespList;
    }

    /**
     * 递归构建子节点
     *
     * @param root
     * @param appExerciseTypes
     */
    private void buildChildrenTypeTree(AppTypeTreeResp root, List<AppExerciseType> appExerciseTypes) {
        List<AppTypeTreeResp> childrenList = new ArrayList<>();
        // 查询子节点
        appExerciseTypes.stream().filter(p -> p.getParentId().intValue() == root.getTypeId().intValue()).forEach(item -> {
            AppTypeTreeResp children = new AppTypeTreeResp();
            children.setTypeId(item.getTypeId());
            children.setLabel(item.getTypeName());
            // 递归构建子节点
            buildChildrenTypeTree(children, appExerciseTypes);
            childrenList.add(children);
        });

        // 有子节点，才加入到上级节点中
        if (childrenList.size() > 0) {
            root.setDisabled(true);
            root.setChildren(childrenList);
        }
    }


    /**
     * 后台搜索树
     *
     * @return
     */
    @Override
    public List<AppExerciseTreeResp> backSearchTableTree() {
        List<AppExerciseTreeResp> AppExerciseTreeRespList = new ArrayList<>();

        LambdaQueryWrapper<AppExerciseType> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(AppExerciseType::getOrderNum);
        //查询所有类型
        List<AppExerciseType> appExerciseTypes = this.baseMapper.selectList(queryWrapper);
        //遍历所有为0的数据
        appExerciseTypes.stream().filter(item -> item.getParentId() == 0).forEach(item -> {
            //第一级没有图片
            AppExerciseTreeResp parent = new AppExerciseTreeResp();
            parent.setId(item.getTypeId());
            parent.setComponentType(item.getComponentType());
            parent.setName(item.getTypeName());
            parent.setOrderNum(item.getOrderNum());

            //有下一级
            if (item.getComponentType() == 3) {
                parent.setComponentType(3);
                buildBackChildrenPart(parent);
            } else {
                //没有下一级，查询所有系列的数据 app_exercise_series
                buildChildrenOneService(parent);
            }

            AppExerciseTreeRespList.add(parent);
        });

        return AppExerciseTreeRespList;
    }

    /**
     * 新增(类型，部份，系列)
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean add(ExerciseTypeAddReq req) {
        boolean result = false;
        //保存主类型 还是type，还是service
        if (req.getTid() == 0) {
            //主类型
            AppExerciseType appExerciseType = new AppExerciseType();
            appExerciseType.setTypeName(req.getName());
            appExerciseType.setComponentType(req.getComponentType());
            appExerciseType.setParentId(req.getTid());
            appExerciseType.setOrderNum(req.getOrderNum());
            //新增主类型
            result = this.save(appExerciseType);
        } else if (req.getComponentType() == 0) {
            //系列exercise_service
            AppExerciseSeries appExerciseSeries = new AppExerciseSeries();
            appExerciseSeries.setTitle(req.getName());
            appExerciseSeries.setPath(req.getPath());
            appExerciseSeries.setTime(req.getTime());
            appExerciseSeries.setConsume(req.getConsume());
            appExerciseSeries.setEquip(req.getEquip());
            appExerciseSeries.setFocus(req.getFocus());
            appExerciseSeries.setTId(new Long(req.getTid()));
            //保存系列
            result = this.exerciseSeriesService.save(appExerciseSeries);

            if (result) {
                //新增系列成功.判断是否它是部位，如果是更新部分part表的num数量
                AppExercisePart appExercisePart = this.exercisePartService.getByTid(req.getTid());
                if (Objects.nonNull(appExercisePart)) {
                    //是部位，更新部位的数量
                    appExercisePart.setNum(appExercisePart.getNum() + 1);
                    result = this.exercisePartService.updateById(appExercisePart);
                }
            }
        } else {
            //部位 (exercise_type和exercise_part)
            //部位类型先插入exercise_type
            AppExerciseType appExerciseType = new AppExerciseType();
            appExerciseType.setTypeName(req.getName());
            appExerciseType.setComponentType(req.getComponentType());
            appExerciseType.setParentId(req.getTid());
            appExerciseType.setOrderNum(req.getOrderNum());
            result = this.save(appExerciseType);
            if (result) {
                //再向exercise_part中写入数据
                AppExercisePart appExercisePart = new AppExercisePart();
                appExercisePart.setTId(appExerciseType.getTypeId());
                appExercisePart.setPath(req.getPath());
                appExercisePart.setNum(0);
                result = this.exercisePartService.save(appExercisePart);
            }
        }

        return result;
    }


    /**
     * 查询锻炼部位的数据(后台)
     *
     * @param parent
     */
    private void buildBackChildrenPart(AppExerciseTreeResp parent) {
        List<AppExercisePartResp> list = this.exercisePartService.findByTidAll(parent.getId());
        //设定子类的组件类型
        list.forEach(v -> {
            v.setComponentType(parent.getComponentType());

            //构造子系列
            List<AppExerciseSeriesResp> childrenList = new ArrayList<>();

            //查询系列
            List<AppExerciseSeries> exerciseSeriesList = this.exerciseSeriesService.findByTidAll(v.getId());

            exerciseSeriesList.forEach(item -> {
                AppExerciseSeriesResp appExerciseSeriesResp = new AppExerciseSeriesResp();
                setAppExerciseSeriesResp(item, appExerciseSeriesResp);
                appExerciseSeriesResp.setComponentType(2);
                childrenList.add(appExerciseSeriesResp);
            });

            if (!childrenList.isEmpty()) {
                v.setChildren(childrenList);
            }

        });
        parent.setChildren(list);
    }

    private void setAppExerciseSeriesResp(AppExerciseSeries item, AppExerciseSeriesResp appExerciseSeriesResp) {
        appExerciseSeriesResp.setId(item.getSeriesId());
        appExerciseSeriesResp.setName(item.getTitle());
        appExerciseSeriesResp.setPath(item.getPath());
        appExerciseSeriesResp.setTime(item.getTime());
        appExerciseSeriesResp.setConsume(item.getConsume());
        appExerciseSeriesResp.setTid(item.getTId());
        appExerciseSeriesResp.setEquip(item.getEquip());
        appExerciseSeriesResp.setFocus(item.getFocus());
        appExerciseSeriesResp.setUserLevelId(item.getUserLevelId());
        appExerciseSeriesResp.setTid(item.getTId());
    }


    /**
     * 修改查询详情
     *
     * @param id
     * @return
     */
    @Override
    public AppExecrciseTypeInfoResp searchById(Long id) {
        //1、先查询exercise_type表，如果没有再查询exercise_service
        AppExecrciseTypeInfoResp resp = this.baseMapper.searchById(id);
        //2、判断是否是exercise_type
        if (Objects.nonNull(resp)) {
            //连表查询exercise_type表和exercise_part表
            if (resp.getTid() > 0 && resp.getComponentType() == 3) {
                AppExercisePart exercisePart = this.exercisePartService.getByTid(resp.getId().intValue());
                resp.setPath(exercisePart.getPath());
            }
        } else {
            //如果没有再查询exercise_service
            AppExerciseSeries exerciseService = this.exerciseSeriesService.getById(id);
            resp = new AppExecrciseTypeInfoResp();
            resp.setId(exerciseService.getSeriesId());
            resp.setName(exerciseService.getTitle());
            resp.setPath(exerciseService.getPath());
            resp.setTid(exerciseService.getTId().intValue());
            resp.setTime(exerciseService.getTime());
            resp.setConsume(exerciseService.getConsume());
            resp.setEquip(exerciseService.getEquip());
            resp.setFocus(exerciseService.getFocus());
            //查询上级节点的名称
            AppExerciseType exerciseType = this.getById(resp.getTid());
            resp.setTname(exerciseType.getTypeName());
            resp.setComponentType(-1);
        }
        return resp;
    }

    /**
     * 修改锻炼类型
     *
     * @param req
     * @return
     */
    @Override
    public boolean edit(ExerciseTypeEditReq req) {
        boolean result = false;
        //系列exercise_service
        if (req.getComponentType() == -1) {
            AppExerciseSeries dbServices = this.exerciseSeriesService.getById(req.getId());
            if (Objects.isNull(dbServices)) {
                throw new RecordNotFoundException();
            }
            dbServices.setTitle(req.getName());
            dbServices.setPath(req.getPath());
            dbServices.setTime(req.getTime());
            dbServices.setConsume(req.getConsume());
            dbServices.setEquip(req.getEquip());
            dbServices.setFocus(req.getFocus());
            dbServices.setTId(req.getTid().longValue());
            result = this.exerciseSeriesService.updateById(dbServices);
        } else {
            //连表查询exercise_type表和exercise_part表
            //只更新exercise_type表
            AppExerciseType dbType = this.getById(req.getId());
            if (Objects.isNull(dbType)) {
                throw new RecordNotFoundException();
            }
            dbType.setTypeName(req.getName());
            dbType.setOrderNum(req.getOrderNum());
            result = this.updateById(dbType);
            //更新exercise_part表的图片
            if (req.getTid() > 0) {
                AppExercisePart byTid = this.exercisePartService.getByTid(req.getTid());
                if (Objects.isNull(byTid)) {
                    throw new RecordNotFoundException();
                }
                byTid.setPath(req.getPath());
                result = this.exercisePartService.updateById(byTid);
            }
        }
        return result;
    }

    /**
     * 根据id查询类型
     * @param sId
     * @return
     */
    @Override
    public AppExerciseType findById(Long sId) {
        return this.getById(sId);
    }


}




